/**
 * 只支持浏览器环境
 * */

/**
 * @param fn 要执行的函数
 * @param step 间隔
 * */
export interface IInitObj {
    fn: any
    interval: number
}

/**
 * @param finalTimer 要执行的时间点
 * */
export interface IQueueObj extends IInitObj{
    id:number
    finalTimer:number
}

export default class TimerSingleton {
    /*
    * _queue 要遍历的队列
    * _id 队列中每个对象的以为标识
    * _requestAnimationFrameId requestAnimationFrame的标识
    * */
    private static _queue:IQueueObj[] = [];
    private static _id:number = 0;
    private static _requestAnimationFrameId:number = -1;

    constructor() {
        throw '这是一个单例类';
    }

    static get queue(): IQueueObj[] {
        return TimerSingleton._queue;
    }

    static getCurrentUTC(){
        const d = new Date();
        const year = d.getUTCFullYear();
        const month = d.getUTCMonth()+1;
        const day = d.getUTCDate()===0?7:d.getUTCDate();
        const h = d.getUTCHours();
        const minute = d.getUTCMinutes();
        const s = d.getUTCSeconds();
        const ms = d.getUTCMilliseconds();
        return Date.UTC(year,month,day,h,minute,s,ms);
    }

    static run(){
        if(TimerSingleton._requestAnimationFrameId!==-1){
            TimerSingleton.stop(TimerSingleton._requestAnimationFrameId);
            TimerSingleton.loop();
            TimerSingleton._requestAnimationFrameId = requestAnimationFrame(TimerSingleton.run);
            return TimerSingleton._requestAnimationFrameId;
        }
        TimerSingleton.loop();
        TimerSingleton._requestAnimationFrameId = requestAnimationFrame(TimerSingleton.run);
        return TimerSingleton._requestAnimationFrameId;
    }

    static stop(requestAnimationFrameId:number){
        cancelAnimationFrame(requestAnimationFrameId);
    }

    private static loop(){
        const _queue =  TimerSingleton.queue;
        for(let i=0;i<_queue.length;i++){
            if(_queue[i].finalTimer<=TimerSingleton.getCurrentUTC()){
                _queue[i].fn();
                _queue[i].finalTimer = TimerSingleton.getCurrentUTC()+_queue[i].interval;
            }
        }
    }

    private static init(data:IInitObj):IQueueObj{
        const finalTimer = TimerSingleton.getCurrentUTC()+data.interval;
        const id = TimerSingleton._id++;
        return Object.assign({finalTimer,id},data);
    }

    static push(data:IInitObj):IQueueObj{
        const _data = TimerSingleton.init(data);
        TimerSingleton.queue.push(_data);
        return _data;
    }

    static pop(id:number){
        const _queue= TimerSingleton.queue;
        const length = _queue.length;
        for(let i=0;i<length;i++){
            if(_queue[i].id===id){
                return  TimerSingleton.queue.slice(i,1);
            }
        }
        return -1;
    }

}